package com.xinsoft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.CusUpkeepEntryDTO;
import com.xinsoft.entity.dto.CusUpkeepPlanDTO;
import com.xinsoft.entity.dto.CusUpkeepPlanParam;
import com.xinsoft.entity.po.*;
import com.xinsoft.entity.vo.CusDevicePlanVo;
import com.xinsoft.mapper.CusUpkeepPlanMapper;
import com.xinsoft.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author lijie
 * @description 针对表【cus_upkeep_plan(保养计划)】的数据库操作Service实现
 * @createDate 2023-06-14 09:52:17
 */
@Service
@Slf4j
public class CusUpkeepPlanServiceImpl extends ServiceImpl<CusUpkeepPlanMapper, CusUpkeepPlan>
        implements CusUpkeepPlanService {
    @Resource
    CusUpkeepPlanMapper cusUpkeepPlanMapper;

    @Resource
    CusUpkeepPlanEntryService planEntryService;

    @Resource
    CusUpkeepPlanSpareService spareService;

    @Resource
    SysUserService userService;

    @Resource
    SysDocumentNumService sysDocumentNumService;

    @Resource
    CusUpkeepService upkeepService;

    @Resource
    SysDeptService deptService;

    @Resource
    CusUpkeepOrderEntryService orderEntryService;

    @Resource
    CusUpkeepOrderPartService orderPartService;

    @Resource
    CusPatrolService patrolService;

    @Override
    public Object findPageListByParam(CusUpkeepPlanParam param) {
        //分页
        Page<CusUpkeepPlan> page = new Page<CusUpkeepPlan>(param.getCurrentPage(), param.getPageSize());
        LambdaQueryWrapper<CusUpkeepPlan> queryWrapper = new LambdaQueryWrapper<>();
        //查询条件
        queryWrapper
                .like(StrUtil.isNotBlank(param.getPlanName()), CusUpkeepPlan::getPlanName, param.getPlanName())
                .eq(ObjectUtil.isNotNull(param.getDoAble()), CusUpkeepPlan::getDoAble, param.getDoAble())
                .eq(ObjectUtil.isNotNull(param.getUpkeepPersonId()), CusUpkeepPlan::getUpkeepPersonId, param.getUpkeepPersonId())
                .lt(StrUtil.isNotBlank(param.getStartTime()), CusUpkeepPlan::getPlanStartTime, param.getStartTime())
                .gt(StrUtil.isNotBlank(param.getEndTime()), CusUpkeepPlan::getPlanEndTime, param.getEndTime())
                .orderByDesc(CusUpkeepPlan::getPlanStartTime);
        IPage<CusUpkeepPlan> resultPage = cusUpkeepPlanMapper.selectPage(page, queryWrapper);
        //返回值
        return resultPage;
    }

    @Override
    public void tempSave(CusUpkeepPlanDTO cusUpkeepPlan) {
        // 暂存有新增和编辑场景
        if (cusUpkeepPlan.getId() == null) {
            cusUpkeepPlan.setPlanStatus(Const.PLAN_STATUS_WAIT);
            // 更新计划单号
            sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.UPKEEP_PLAN_DOCUMENT);
            cusUpkeepPlanMapper.insert(cusUpkeepPlan);
            // 解析计划设备项目关系表
            if (cusUpkeepPlan.getUpkeepPlanDeviceList() != null) {
                this.dealList(cusUpkeepPlan);
            } else {
                throw new BDException("操作失败，不包含设备项目集合！");
            }
            // 解析计划备件表
            if (cusUpkeepPlan.getUpkeepPlanSpareList() != null) {
                for (int i = 0; i < cusUpkeepPlan.getUpkeepPlanSpareList().size(); i++) {
                    cusUpkeepPlan.getUpkeepPlanSpareList().get(i).setUpkeepPlanId(cusUpkeepPlan.getId());
                }
                spareService.saveBatch(cusUpkeepPlan.getUpkeepPlanSpareList());
            }
        } else {
            // 解析计划设备项目关系表
            if (cusUpkeepPlan.getUpkeepPlanDeviceList() != null) {
                planEntryService.remove(new QueryWrapper<CusUpkeepPlanEntry>().eq("upkeep_plan_id", cusUpkeepPlan.getId()));
                this.dealList(cusUpkeepPlan);
            } else {
                throw new BDException("操作失败，不包含设备项目集合！");
            }
            // 解析计划备件表
            if (cusUpkeepPlan.getUpkeepPlanSpareList() != null) {
                spareService.remove(new QueryWrapper<CusUpkeepPlanSpare>().eq("upkeep_plan_id", cusUpkeepPlan.getId()));
                // 补充计划id
                for (int i = 0; i < cusUpkeepPlan.getUpkeepPlanSpareList().size(); i++) {
                    cusUpkeepPlan.getUpkeepPlanSpareList().get(i).setUpkeepPlanId(cusUpkeepPlan.getId());
                }
                spareService.saveBatch(cusUpkeepPlan.getUpkeepPlanSpareList());
            }
            cusUpkeepPlanMapper.updateById(cusUpkeepPlan);
        }
    }

    public void dealList(CusUpkeepPlanDTO cusUpkeepPlan) {
        for (int i = 0; i < cusUpkeepPlan.getUpkeepPlanDeviceList().size(); i++) {
            for (int j = 0; j < cusUpkeepPlan.getUpkeepPlanDeviceList().get(i).getUpkeepPlanEntryList().size(); j++) {
                CusUpkeepEntryDTO cusUpkeepEntryDTO = cusUpkeepPlan.getUpkeepPlanDeviceList().get(i).getUpkeepPlanEntryList().get(j);
                CusUpkeepPlanEntry entry = new CusUpkeepPlanEntry();
                entry.setUpkeepPlanId(cusUpkeepPlan.getId());
                entry.setDeviceId(cusUpkeepPlan.getUpkeepPlanDeviceList().get(i).getDeviceId());
                entry.setUpkeepEntryId(cusUpkeepEntryDTO.getUpkeepEntryId());
                BeanUtil.copyProperties(cusUpkeepEntryDTO, entry);
                // 乘积出来具体的关系条数
                planEntryService.save(entry);
            }
        }
    }

    @Override
    public void submit(CusUpkeepPlanDTO cusUpkeepPlan) {
        // 新增提交
        if (cusUpkeepPlan.getId() == null) {
            cusUpkeepPlan.setPlanStatus(Const.PLAN_STATUS_NORMAL);
            sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.UPKEEP_PLAN_DOCUMENT);
            cusUpkeepPlanMapper.insert(cusUpkeepPlan);
            // 解析计划设备项目关系表
            if (cusUpkeepPlan.getUpkeepPlanDeviceList() != null) {
                this.dealList(cusUpkeepPlan);
            } else {
                throw new BDException("操作失败，不包含设备项目集合！");
            }
            // 解析计划备件表
            if (cusUpkeepPlan.getUpkeepPlanSpareList() != null) {
                for (int i = 0; i < cusUpkeepPlan.getUpkeepPlanSpareList().size(); i++) {
                    cusUpkeepPlan.getUpkeepPlanSpareList().get(i).setUpkeepPlanId(cusUpkeepPlan.getId());
                }
                spareService.saveBatch(cusUpkeepPlan.getUpkeepPlanSpareList());
            }
        } else {
            // 解析计划设备项目关系表
            if (cusUpkeepPlan.getUpkeepPlanDeviceList() != null) {
                planEntryService.remove(new QueryWrapper<CusUpkeepPlanEntry>().eq("upkeep_plan_id", cusUpkeepPlan.getId()));
                this.dealList(cusUpkeepPlan);
            } else {
                throw new BDException("操作失败，不包含设备项目集合！");
            }
            // 解析计划备件表
            if (cusUpkeepPlan.getUpkeepPlanSpareList() != null) {
                spareService.remove(new QueryWrapper<CusUpkeepPlanSpare>().eq("upkeep_plan_id", cusUpkeepPlan.getId()));
                spareService.saveBatch(cusUpkeepPlan.getUpkeepPlanSpareList());
            }
            cusUpkeepPlan.setPlanStatus(Const.PLAN_STATUS_NORMAL);
            cusUpkeepPlanMapper.updateById(cusUpkeepPlan);
        }
    }

    @Override
    public CusUpkeepPlan getByInfoById(Integer id) {
        CusUpkeepPlan plan = cusUpkeepPlanMapper.selectById(id);
        // 负责人
        SysUser user = userService.getById(plan.getUpkeepPersonId());
        if (user != null) {
            plan.setUpkeepPersonName(user.getRealName());
        }
        if (user != null) {
            plan.setUpkeepPersonName(user.getRealName());
            plan.setUpkeepPersonDept(deptService.getById(user.getDeptId()).getDeptName());
            plan.setUpkeepPersonTel(user.getMobile());
        }
        // 追加设备名设备编号集合
        List<CusDevicePlanVo> planVos = cusUpkeepPlanMapper.getDeviceListByPlanId(id);
        if (planVos.size() > 0) {
            plan.setDevicePlanList(planVos);
        }
        // 追加保养项目保养名称，设备与项目为父子级关系
        for (int i = 0; i < planVos.size(); i++) {
            List<CusUpkeepPlanEntry> listCp = cusUpkeepPlanMapper.getEntityInfoByDeviceId(planVos.get(i).getDeviceId(), id);
            if (listCp.size() > 0) {
                planVos.get(i).setUpkeepPlanEntryList(listCp);
            }
        }

        // 追加备件名，备件编号，备件型号
        List<CusUpkeepPlanSpare> listSp = cusUpkeepPlanMapper.getMaterialInfoById(id);
        if (listSp.size() > 0) {
            plan.setUpkeepPlanSpareList(listSp);
        }
        return plan;
    }

    @Override
    public void planToTask() {
        // 检索出需要生成执行的计划
        // 找出符合要求的所有巡检计划 现在>开始时间,现在<结束时间,启用状态，提交状态
        List<CusUpkeepPlan> list = cusUpkeepPlanMapper.selectList(new QueryWrapper<CusUpkeepPlan>()
                .eq("do_able", Const.AUDIT_STATUS_NORMAL)
                .eq("plan_status", Const.PLAN_STATUS_NORMAL)
                .eq("do_delete", Const.DEL_FLAG_NORMAL)
                .gt("plan_end_time", DateUtil.formatDateTime(new Date())));
        if (list.size() > 0) {
            // 循环遍历，每个计划生成执行时需要一个个设备按计划中明细子项的间隔天数生成
            for (int i = 0; i < list.size(); i++) {
                // 获取本保养计划
                CusUpkeepPlan cusUpkeepPlan = list.get(i);
                // 获取该计划的明细保养子集-每个设备生成一条保养执行
                List<CusUpkeepPlanEntry> entryList = planEntryService.list(new QueryWrapper<CusUpkeepPlanEntry>().eq("upkeep_plan_id", cusUpkeepPlan.getId()));
                if (entryList.size() > 0) {
                    // 取出该计划所有备件
                    List<CusUpkeepPlanSpare> spareList = spareService.list(new QueryWrapper<CusUpkeepPlanSpare>().eq("upkeep_plan_id", cusUpkeepPlan.getId()));
                    // 针对子集和间隔时间是否满足要求生成保养执行
                    for (int j = 0; j < entryList.size(); j++) {
                        CusUpkeepPlanEntry entry = entryList.get(j);
                        // 该子项周期内总共允许发生次数
                        int last = (int) ((cusUpkeepPlan.getPlanEndTime().getTime() - cusUpkeepPlan.getPlanStartTime().getTime()) / (1000 * 60 * 60 * 24));
                        int count = last / entry.getIntervalDay();
                        if (count < 1) {
                            return;
                        } else {
                            // 如果遍历到今天的日期能=计划开始时间 + 间隔次数*间隔小时。说明今天该项可以生成执行
                            for (int k = 0; k < count; k++) {
                                String day = DateUtil.formatDate(DateUtil.offsetDay(cusUpkeepPlan.getPlanStartTime(), k * entry.getIntervalDay()));
                                if (day.equals(DateUtil.formatDate(new Date()))) {
                                    // 查看该针对该计划该设备的保养执行是否生成过
                                    // 注入基础数据，填充待完善数据: 保养工单 工单条目 工单备件
                                    CusUpkeep cusUpkeep = upkeepService.getOne(new QueryWrapper<CusUpkeep>().eq("upkeep_plan_id", cusUpkeepPlan.getId())
                                            .eq("device_id", entry.getDeviceId()));
                                    if (cusUpkeep == null) {
                                        CusUpkeep cusUpkeep1 = new CusUpkeep();
                                        BeanUtil.copyProperties(entry, cusUpkeep1);
                                        // 注入保养单号
                                        String code = sysDocumentNumService.getSysDocumentNumByDocumentId(Const.DOCUMENT_ID.PATROL_ORDER_DOCUMENT);
                                        sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.PATROL_ORDER_DOCUMENT);
                                        cusUpkeep1.setUpkeepNum(code);
                                        cusUpkeep1.setUpkeepPersonId(cusUpkeepPlan.getUpkeepPersonId());
                                        cusUpkeep1.setUpkeepPlanId(cusUpkeepPlan.getId());
                                        cusUpkeep1.setUpkeepLevel(10391);
                                        cusUpkeep1.setUpkeepStatus(Const.UPKEEP_STATUS_WAIT);
                                        cusUpkeep1.setUpkeepStartTime(DateUtil.parseDate(DateUtil.today()));
                                        cusUpkeep1.setUpkeepEndTime(DateUtil.offsetDay(new Date(), entry.getIntervalDay()));
                                        // 注入保养工单
                                        upkeepService.save(cusUpkeep1);
                                        // 注入保养工单条目表
                                        CusUpkeepOrderEntry orderEntry = new CusUpkeepOrderEntry();
                                        BeanUtil.copyProperties(entry, orderEntry);
                                        orderEntry.setUpkeepId(cusUpkeep1.getId());
                                        orderEntryService.save(orderEntry);
                                        // 注入保养工单备件 只需注入一次
                                        if (spareList.size() > 0) {
                                            List<CusUpkeepOrderPart> orderPartList = new ArrayList<>();
                                            for (int l = 0; l < spareList.size(); l++) {
                                                CusUpkeepOrderPart cusUpkeepOrderPart = new CusUpkeepOrderPart();
                                                BeanUtil.copyProperties(spareList.get(l), cusUpkeepOrderPart);
                                                cusUpkeepOrderPart.setUpkeepId(cusUpkeep1.getId());
                                                orderPartList.add(cusUpkeepOrderPart);
                                            }
                                            orderPartService.saveBatch(orderPartList);
                                        }
                                    } else {
                                        // 注入保养工单条目表
                                        CusUpkeepOrderEntry orderEntry = new CusUpkeepOrderEntry();
                                        BeanUtil.copyProperties(entry, orderEntry);
                                        orderEntry.setUpkeepId(cusUpkeep.getId());
                                        orderEntryService.save(orderEntry);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } else {
            log.info("今日暂无需要生成的执行");
        }

    }

    @Override
    public void upKeepChangeToTimeOut() {
        List<CusUpkeep> list = upkeepService.list(new QueryWrapper<CusUpkeep>().eq("upkeep_status",Const.UPKEEP_STATUS_WAIT));
        if(list.size() > 0){
            for (int i = 0; i < list.size(); i++) {
                CusUpkeep cusUpkeep = list.get(i);
                if(cusUpkeep.getUpkeepEndTime().getTime() < System.currentTimeMillis()){
                    cusUpkeep.setUpkeepStatus(Const.UPKEEP_STATUS_TIMEOUT);
                    upkeepService.updateById(cusUpkeep);
                }
            }
        }
    }

    @Override
    public void patrolChangeToTimeOut() {
        List<CusPatrol> list = patrolService.list(new QueryWrapper<CusPatrol>().eq("patrol_status",Const.UPKEEP_STATUS_WAIT));
        if(list.size() > 0){
            for (int i = 0; i < list.size(); i++) {
                CusPatrol cusPatrol = list.get(i);
                if(cusPatrol.getCompleteTime().getTime() < System.currentTimeMillis()){
                    cusPatrol.setPatrolStatus(Const.UPKEEP_STATUS_TIMEOUT);
                    patrolService.updateById(cusPatrol);
                }
            }
        }
    }
}




